﻿#include "RecvSocketMsg.h"
#include "unit.h"
#include "Msg.h"
#include "protocolstream.h"

#include <QString>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QDebug>
#include <QThread>

RecvSocketMsg::RecvSocketMsg(QTcpSocket *socket, QObject *parent)
    : QObject(parent),
      m_pTcpSocket(socket),
      m_seq(-1)
{
    qDebug() << "RecvSocketMsg";
}

void RecvSocketMsg::initConection()
{
    qDebug() << "initConection";

}

// tcp消息处理
void RecvSocketMsg::SltReadyRead()
{
    qDebug() << "SltReadyRead() thread" << QThread::currentThreadId();
    //缓冲区没有数据，直接无视
    if( m_pTcpSocket->bytesAvailable() <= 0 )
    {
        qDebug() << "no bytes";
        return;
    }
    //临时获得从缓存区取出来的数据，但是不确定每次取出来的是多少。
    QByteArray buffer;
    //如果是信号readyRead触发的，使用readAll时会一次把这一次可用的数据全总读取出来
    //所以使用while(m_tcpClient->bytesAvailable())意义不大，其实只执行一次。
    buffer = m_pTcpSocket->readAll();
    m_buffer.append(buffer);
    qDebug() << m_buffer;
    while(true)
    {
        //不够一个包头大小
        if (m_buffer.size() < sizeof(msg))
        {
            qDebug() << "buffer is not enough for a package header, m_buffer.size() = " << m_buffer.size() << ", sizeof(msg)=" << sizeof(msg);
            break;
        }

        //不够一个整包大小
        msg header;
        memcpy(&header, m_buffer.constData(), sizeof(msg));
        if (m_buffer.size() < header.packagesize + sizeof(msg))
            break;

        //去除包头
        m_buffer = m_buffer.mid(sizeof(msg));

        if (!Process(m_buffer.constData(), header.packagesize))
        {
            qDebug() << "Process error, close TcpConnection";
            m_pTcpSocket->abort();
        }
        //去掉包体
        m_buffer = m_buffer.mid(header.packagesize);
    }
}


bool RecvSocketMsg::Process(const char* inbuf, size_t length)
{
    yt::BinaryReadStream2 readStream(inbuf, length);
    int cmd;
    if (!readStream.Read(cmd))
    {
        qDebug() << "read cmd error !!!";
        return false;
    }

    //int seq;
    if (!readStream.Read(m_seq))
    {
        qDebug() << "read seq error !!!";
        return false;
    }

    std::string data;
    size_t datalength;
    if (!readStream.Read(&data, 0, datalength))
    {
        qDebug() << "read data error !!!";
        return false;
    }

    qDebug() << "Recv from client: cmd=" << cmd << ", seq=" << m_seq << ", header.packagesize:" << length << ", data=" << data.c_str() << ", datalength=" << datalength;

    switch(cmd)
    {
        //心跳包
        case msg_type_heartbeart:
        {
            //OnHeartbeatResponse();
        }
            break;

        //注册
        case msg_type_register:
        {
            qDebug() << "注册";
            OnRegisterResult(data.c_str(), data.size());
        }
            break;

        //登录
        case msg_type_login:
        {
            //OnLoginResponse(data, conn);
            qDebug() << "登录";
        }
            break;
        default:
            qDebug() << "unsupport cmd, cmd:" << cmd;
            return false;
    }
    return true;
}

void RecvSocketMsg::OnRegisterResult(const char* data,int length)
{
    QByteArray jsonData(data,length);
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument document = QJsonDocument::fromJson(jsonData,&jsonError);
    // 解析未发生错误
    if(!document.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        // JSON 文档为对象
        if (document.isObject())
        {
            // 转化为对象
            QJsonObject jsonObj = document.object();
            int code = jsonObj.value("code").toInt();
            switch(code)
            {
                case error_code_ok:
                    Q_EMIT signalStatus(RegisterOk);
                break;

                case error_code_registerfail:
                    Q_EMIT signalStatus(RegisterFailed);
                break;

                case error_code_registeralready:
                    Q_EMIT signalStatus(RegisterAlready);
                break;

                default:
                    qDebug() << "unsupport code, code: " << code << ",msg: " << jsonObj.value("msg").toString();
                break;
            }
        }
    }
}
